package com.woniuxy.Aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author：向天浩
 * @Date：2022/1/20 20:16
 * @Description :TODO
 */
@Aspect  //这个注解是aop要用的，表示这个是 切面
@Component // 这个是spring需要的，表示这个类是组件，可以自动帮我注册到ioc容器中成为bean
public class MyAnnoAspectj {

    //方法上的注释Pointcut；切入点（spring框架中AOP的术语）表示我们可以在哪些包下面，哪些方法切入进去
    /*
     *功能描述
     * 注解中的myPointCut方法，其实就是上面定义pointcut切点注解所修饰的方法名，那只是个代理对象,不需要写具体方法，
     * 相当于xml声明切面的id名，如下，相当于id="embark",用于供其他通知类型引用)
     */
    @Pointcut("execution(* com.woniuxy.Service.*.*(..))")
    private void myPointCut(){};

    //前置通知
    @Before("myPointCut()")
    public void myBefore(JoinPoint joinpoint){
        System.out.println("前置通知：模拟判断是否有@Transcational注解…… 这是使用注解的方式");
        System.out.print("目标类是："+joinpoint.getTarget().getClass().getName());
        System.out.println("，被织入的增强目标的方法是："+joinpoint.getSignature().getName());
    }
    //后置通知
    @AfterReturning("myPointCut()")
    public void myAfterReturning(JoinPoint joinpoint){
        System.out.println("后置通知：模拟事务的提交……");
        System.out.print("目标类是："+joinpoint.getTarget());
        System.out.println("，被织入的增强目标的方法是："+joinpoint.getSignature().getName());
    }
    //环绕通知：不推荐使用
    @Around("myPointCut()")
    public Object myAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("环绕开始：执行目标方法之前……");
        Object proceed = proceedingJoinPoint.proceed();
        System.out.println("环绕结束：执行目标方法之后……");
        return proceed;
    }
    //异常通知
    @AfterThrowing(value = "myPointCut()",throwing = "e")
    public void myAfterThrowing(JoinPoint joinPoint,Throwable e){
        System.out.println("异常通知");
        System.out.println("报错信息"+e.getMessage());
    }
    //最终通知
    @After("myPointCut()")
    public void myAfter(){
        System.out.println("最终通知：模拟方法结束后释放资源，关闭SqlSession……");
    }

}
